/**
 * Copyright 2012 ibiblio
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ibiblio.terasaur.controller

import org.ibiblio.terasaur.item.PermissionHelper
import org.ibiblio.terasaur.search.DateHelper
import org.ibiblio.terasaur.user.User
import org.ibiblio.terasaur.item.Item
import org.ibiblio.terasaur.item.Collection
import org.springframework.security.acls.domain.BasePermission
import org.ibiblio.terasaur.ui.StringCleaner

class ItemMixin {
    private static StringCleaner stringCleaner = new StringCleaner()

    /**
     * Get Item instance for the current request.  Check published date
     * and deleted fields, as well as the current user's access rights.
     *
     * Returns an Item if everything checks out, null if the item isn't
     * accessible by the current user.
     *
     * @param Map HTTP request params
     * @param SpringSecurityService
     * @return Item
     */
    public Item getItemInstance() {
        Item item = null
        try {
            Long itemId = Long.parseLong(params.id)
            item = getItemInstanceForId(itemId)
        } catch (NumberFormatException e) {
            // pass
        }
        return item
    }

    public Item getItemInstanceForId(Long itemId) {
        boolean isPublic = true
        Item item = Item.get(itemId)

        // Check deleted
        if (item && item.deleted) {
            isPublic = false
        }

        // Check published date
        if (item && item.published.isAfter(DateHelper.now())) {
            isPublic = false
        }

        if (!isPublic && !canEditItem(item)) {
            item = null
        }

        return item
    }

    /**
     * Mockable for unit testing.  The controller must have the following
     * injected services:
     *  - permissionHelper
     *  - springSecurityService
     *  - aclUtilService
     *
     * @param Item
     * @return
     */
    public boolean canEditItem(Item item) {
        if (permissionHelper.isAdmin(springSecurityService.currentUser) ||
            aclUtilService.hasPermission(springSecurityService.authentication, item, BasePermission.WRITE)) {
            return true
        } else {
            return false
        }
    }

    public void setAccessDeniedRedirect() {
        def redirectUri
        if (springSecurityService.currentUser) {
            redirectUri = grailsApplication.config.grails.plugins.springsecurity.adh.errorPage
        } else {
            redirectUri = grailsApplication.config.grails.plugins.springsecurity.auth.loginFormUrl
        }
        redirect(uri: redirectUri)
    }

    public String getItemSaveErrorCode(Item item) {
        String code
        if (item && item.errors.hasFieldErrors()) {
            if (item.errors.hasFieldErrors('version')) {
                code = 'item.update.version.changed.message'
            } else {
                code = 'item.update.field.error.message'
            }
        } else {
            code = 'item.update.general.message'
        }
        return code
    }

    /**
     * Returns map containing information for generating the appropriate
     * img tag to display a collection logo.  Input parameter can be either an
     * Item or a Collection.
     *
     * Map keys:
     *  - src: string for img src attribute
     *  - alt: string for img alt attribute
     *  - link: collection browse url for an a href tag around the logo image
     *
     * @param collection or item
     * @return
     */
    public Map getCollectionLogo(param) {
        if (!urlHelper) {
            throw new Exception('Controller class must define a urlHelper member object')
        }

        Map logoMap = null
        Collection collection = null
        if (param == null) {
            return logoMap
        }

        if (param instanceof Item) {
            collection = param.collection
        } else if (param instanceof Collection) {
            collection = param
        } else {
            throw new Exception('Input parameter must be type Item or Collection')
        }

        if (collection.id != 1 && collection.logoUrl) {
            logoMap = [
                src: collection.logoUrl,
                alt: stringCleaner.clean(collection.name),
                link: urlHelper.collectionLink(collection, 'browse')
                ]
        }
        return logoMap
    }

}
